﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Arborium;

namespace ArboriumTests
{
    [TestClass]
    public class StabilityTests
    {
        private Random random = new Random((int)DateTime.Now.Ticks);

        [TestMethod]
        public void Stability()
        {
            const int maxTests = 10000;
            const int minChildren = 0;
            const int maxChildren = 5;
            const double probability = 0.90;

            CreateAndVerifyTrees(maxTests, minChildren, maxChildren, probability, @"c:\windows\temp\stability.arbo");
        }

        [TestMethod]
        public void BigTrees()
        {
            const int maxTests = 10;
            const int minChildren = 0;
            const int maxChildren = 20;
            const double probability = 0.95;

            CreateAndVerifyTrees(maxTests, minChildren, maxChildren, probability, @"c:\windows\temp\big_trees.arbo");
        }

        private AElement GenerateTree(int minimumChildren, int maximumChildren, double probability)
        {
            AElement root = new AElement();

            GenerateTree(root, minimumChildren, maximumChildren, probability);

            return root;
        }

        private void GenerateTree(AElement node, int minimumChildren, int maximumChildren, double probability, int level = 0)
        {
            if (random.NextDouble() < probability)
            {
                int numChildren = random.Next(maximumChildren - minimumChildren) + minimumChildren;

                for (int x = 0; x < numChildren; x++)
                {
                    Guid nodeGuid = Guid.NewGuid();

                    AElement child = new AElement()
                    {
                        MetaData = AData.FromGuid(nodeGuid),
                        Data = AData.FromUtf8String(String.Format("LEVEL: {0}, NODE: {1}", level, nodeGuid))
                    };

                    GenerateTree(child, minimumChildren, maximumChildren, probability * probability, level++);

                    node.Add(child);
                }
            }
        }

        private void CreateAndVerifyTrees(int maxTests, int minChildren, int maxChildren, double probability, string fileName)
        {
            for (int x = 0; x < maxTests; x++)
            {
                AElement originalTree = GenerateTree(minChildren, maxChildren, probability);
                string originalTreeString = originalTree.TreeToString();
                originalTree.Save(fileName);

                // Statistics stats = originalTree.Statistics;

                Assert.IsTrue(new FileInfo(fileName).Length > 0);

                AElement currentTree = AElement.Load(fileName);
                string currentTreeString = currentTree.TreeToString();

                Assert.AreEqual(originalTreeString, currentTreeString);
            }
        }

    }
}
